/**
 * index_iterator.cpp
 */
#include <cassert>
#include <utility>

#include "buffer/buffer_pool_manager.h"
#include "common/config.h"
#include "common/macros.h"
#include "storage/index/index_iterator.h"
#include "storage/page/b_plus_tree_page.h"

namespace bustub {

/*
 * NOTE: you can change the destructor/constructor method here
 * set your own input parameters
 */
INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::IndexIterator(ReadPageGuard &&page_guarded, int index, BufferPoolManager *bpm)
    : page_guarded_(std::move(page_guarded)), index_(index), bpm_(bpm) {}

INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::IndexIterator(IndexIterator &&that) noexcept {
  IndexIterator(std::move(that.page_guarded_), that.index_, that.bpm_);
}

INDEX_TEMPLATE_ARGUMENTS
INDEXITERATOR_TYPE::~IndexIterator() = default;

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::IsEnd() -> bool {
  BUSTUB_ASSERT(page_guarded_.PageId() != INVALID_PAGE_ID, "undefined");
  auto page_ptr = page_guarded_.As<LeafPage>();
  return page_ptr->GetNextPageId() == INVALID_PAGE_ID && index_ == page_ptr->GetSize() - 1;
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator=(INDEXITERATOR_TYPE &&that) noexcept -> INDEXITERATOR_TYPE & {
  this->index_ = that.index_;
  this->bpm_ = that.bpm_;
  that.bpm_ = nullptr;
  this->page_guarded_ = std::move(that.page_guarded_);
  return *this;
}

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator*() -> const MappingType & { return page_guarded_.As<LeafPage>()->At(index_); }

INDEX_TEMPLATE_ARGUMENTS
auto INDEXITERATOR_TYPE::operator++() -> INDEXITERATOR_TYPE & {
  if (index_ < page_guarded_.As<LeafPage>()->GetSize() - 1) {
    index_++;
    return *this;
  }
  auto next_page_id = page_guarded_.As<LeafPage>()->GetNextPageId();
  if (next_page_id == INVALID_PAGE_ID) {
    index_ = -1;
    return *this;
  }
  page_guarded_ = bpm_->FetchPageRead(next_page_id);
  index_ = 0;
  return *this;
}

template class IndexIterator<GenericKey<4>, RID, GenericComparator<4>>;

template class IndexIterator<GenericKey<8>, RID, GenericComparator<8>>;

template class IndexIterator<GenericKey<16>, RID, GenericComparator<16>>;

template class IndexIterator<GenericKey<32>, RID, GenericComparator<32>>;

template class IndexIterator<GenericKey<64>, RID, GenericComparator<64>>;

}  // namespace bustub
